package com.erp.warehouse.clouderp_warehouse.service.impl.inbound;

import com.erp.warehouse.clouderp_warehouse.mapper.inbound.InboundOrderItemMapper;
import com.erp.warehouse.clouderp_warehouse.mapper.inbound.InboundOrderMapper;
import com.erp.warehouse.clouderp_warehouse.mapper.inventory.InventoryBatchMapper;
import com.erp.warehouse.clouderp_warehouse.mapper.inventory.InventoryMapper;
import com.erp.warehouse.clouderp_warehouse.mapper.inventory.InventoryOrdinaryMapper;
import com.erp.warehouse.clouderp_warehouse.mapper.inventory.InventorySerialMapper;
import com.erp.warehouse.clouderp_warehouse.mapper.serial.OrderSerialMapper;
import com.erp.warehouse.clouderp_warehouse.pojo.inbound.InboundOrder;
import com.erp.warehouse.clouderp_warehouse.pojo.inbound.InboundOrderCreate;
import com.erp.warehouse.clouderp_warehouse.pojo.inbound.InboundOrderItem;
import com.erp.warehouse.clouderp_warehouse.pojo.inbound.InboundOrderModify;
import com.erp.warehouse.clouderp_warehouse.pojo.inventory.InventorySerial;
import com.erp.warehouse.clouderp_warehouse.pojo.serial.OrderSerial;
import com.erp.warehouse.clouderp_warehouse.service.inbound.InboundOrderService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.comple.erp.pojo.TableStatus;
import org.comple.erp.pojo.warehouse.InboundType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 2025/10/30 14:09
 * author: 向远洋
 */
@Service
@Transactional
public class InboundOrderServiceImpl implements InboundOrderService {
    @Autowired
    private InboundOrderMapper mapper;
    @Autowired
    private InboundOrderItemMapper itemMapper;
    @Autowired
    private InboundOrderMapper inboundOrderMapper;
    @Autowired
    private InboundOrderItemMapper inboundOrderItemMapper;
    @Autowired
    private OrderSerialMapper orderSerialMapper;
    @Autowired
    private InventoryMapper inventoryMapper;
    @Autowired
    private InventoryOrdinaryMapper inventoryOrdinaryMapper;
    @Autowired
    private InventoryBatchMapper inventoryBatchMapper;
    @Autowired
    private InventorySerialMapper inventorySerialMapper;

    @Override
    public boolean addInboundOrder(InboundOrder inboundOrder) {
        return mapper.insert(inboundOrder) == 1;
    }

    @Override
    public boolean modifyInboundOrder(InboundOrder inboundOrder) {
        return mapper.update(inboundOrder) == 1;
    }

    @Override
    public void deleteById(Map<String, Object> params) {
        if (mapper.virtualDeleteById(params) == 1) return;
        throw new RuntimeException("您无法删除该入库单！");
    }

    @Override
    public void deleteByIds(List<Long> ids, String staffId, String companyId) {
        if (mapper.virtualDeleteByIds(ids, staffId, companyId) == ids.size()) return;
        throw new RuntimeException("您无法删除该入库单列表！");
    }

    @Override
    public PageInfo<InboundOrder> findInboundOrderList(Map<String, Object> params) {
        int pageNum = Integer.parseInt(params.get("pageNum").toString());
        int pageSize = Integer.parseInt(params.get("pageSize").toString());
        PageHelper.startPage(pageNum, pageSize);
        List<InboundOrder> list = mapper.selectInboundOrderList(params);
        return new PageInfo<>(list);
    }

    @Override
    public List<InboundOrder> allInboundOrderList(Map<String, Object> params) {
        return inboundOrderMapper.selectInboundOrderList(params);
    }

    @Override
    public void createWithItems(InboundOrderCreate request) {
        // 1. 插入主单
        InboundOrder order = request.getInboundOrder();
        order.setCreatedTime(new Date());
        List<InboundOrderItem> items = request.getInboundOrderItemList();

        // 2. 设置外键：将明细关联到主单，同时根据明细数量、价格修改入库主表的总数量、总价格
        String inboundId = order.getId();
        Integer quantity = 0;
        BigDecimal totalPrice = new BigDecimal("0");
        for (InboundOrderItem item : items) {
            item.setId(UUID.randomUUID().toString());
            item.setInboundId(inboundId); // 关联主单id
            if (item.getType() == 2 && item.getSerialList() != null && !item.getSerialList().isEmpty()) { // 序列号
                List<OrderSerial> list = item.getSerialList().stream()
                        .peek(serial -> {
                            serial.setId(UUID.randomUUID().toString());
                            serial.setOrderId(item.getId()); // 关联明细ID
                        })
                        .collect(Collectors.toList());
                orderSerialMapper.insertOrderSerialList(list);
            }
            quantity += item.getQuantity();
            totalPrice = totalPrice.add(item.getTotalPrice());
        }
        // 3. 插入入库主表和批量插入明细
        order.setTotalQuantity(quantity);
        order.setTotalMoney(totalPrice);
        mapper.insert(order);
        if (items != null && !items.isEmpty()) itemMapper.insertInboundOrderItemList(items);


    }

    @Override
    public InboundOrderCreate getInboundOrderRequest(String id) {
        InboundOrder inboundOrder = inboundOrderMapper.selectInboundOrder(id);
        List<InboundOrderItem> inboundOrderItems = inboundOrderItemMapper.selectInboundOrderItemList(id);
        if (inboundOrderItems != null && !inboundOrderItems.isEmpty()) {
            // 3. 找出所有 type == 2 的明细 ID
            List<String> serialItemIds = inboundOrderItems.stream()
                    .filter(item -> item.getType() != null && item.getType() == 2)
                    .map(InboundOrderItem::getId)
                    .collect(Collectors.toList());

            // 4. 如果有需要加载序列号的明细
            if (!serialItemIds.isEmpty()) {
                // 5. 批量查询这些明细对应的所有序列号
                List<OrderSerial> allSerials = orderSerialMapper.selectOrderSerialList(serialItemIds);

                // 6. 按 orderId（即明细ID）分组
                Map<String, List<OrderSerial>> serialMap = allSerials.stream()
                        .collect(Collectors.groupingBy(OrderSerial::getOrderId));

                // 7. 回填到对应的 InboundOrderItem 中
                for (InboundOrderItem item : inboundOrderItems) {
                    if (item.getType() != null && item.getType() == 2) {
                        List<OrderSerial> serialList = serialMap.get(item.getId());
                        item.setSerialList(serialList != null ? serialList : new ArrayList<>());
                    }
                }
            }
        }

        return new InboundOrderCreate(inboundOrder, inboundOrderItems);
    }

    @Override
    public void modifyWithItems(InboundOrderModify inboundOrderModify) {
        //执行删除操作
        List<String> delList = inboundOrderModify.getDelArr();
        if (!delList.isEmpty()) {
            orderSerialMapper.deleteOrderSerialList(delList);
            inboundOrderItemMapper.deleteInboundOrderItemList(delList);
        }
        //修改操作
        List<InboundOrderItem> modArr = inboundOrderModify.getModArr();
        if (!modArr.isEmpty()) {
            for (InboundOrderItem item : modArr) {
                // 更新明细本身
                inboundOrderItemMapper.updateInboundOrderItem(item);
                // 如果是序列号管理类型（type == 2），同步更新 serialList
                if (item.getType() != null && item.getType() == 2) {
                    // 2.1 删除该明细旧的序列号
                    orderSerialMapper.deleteOrderSerialList(Collections.singletonList(item.getId()));
                    // 2.2 插入新的序列号
                    if (item.getSerialList() != null && !item.getSerialList().isEmpty()) {
                        List<OrderSerial> list = item.getSerialList().stream()
                                .peek(serial -> {
                                    serial.setId(UUID.randomUUID().toString());
                                    serial.setOrderId(item.getId()); // 关联明细ID
                                })
                                .collect(Collectors.toList());
                        orderSerialMapper.insertOrderSerialList(list);
                    }
                }
            }
        }

        //新增操作
        List<InboundOrderItem> addArr = inboundOrderModify.getAddArr();
        InboundOrder inboundOrder = inboundOrderModify.getInboundOrder();
        if (!addArr.isEmpty()) {
            List<OrderSerial> allSerials = new ArrayList<>();
            for (InboundOrderItem item : addArr) {
                String itemId = UUID.randomUUID().toString();
                item.setId(itemId);
                item.setInboundId(inboundOrder.getId());
                // 如果是序列号类型，设置 orderId（即明细ID）
                if (item.getType() != null && item.getType() == 2) {
                    if (item.getSerialList() != null) {
                        item.getSerialList().forEach(serial -> {
                            serial.setId(UUID.randomUUID().toString());
                            serial.setOrderId(itemId); // 关联当前明细
                            allSerials.add(serial); //获取所有serial
                        });
                    }
                }
            }
            inboundOrderItemMapper.insertInboundOrderItemList(addArr);
            // 批量插入序列号（只针对 type==2 的）
            if (!allSerials.isEmpty()) {
                orderSerialMapper.insertOrderSerialList(allSerials);
            }
        }
        // 4. 更新主单（总数量、总金额等）
        boolean modified = inboundOrderModify.getOrderModified();
        if (modified || delList.isEmpty() || !modArr.isEmpty() || !addArr.isEmpty()) {
            // 重新计算总数量和总金额（
            List<InboundOrderItem> inboundOrderItemList = inboundOrderItemMapper.selectInboundOrderItemList(inboundOrder.getId());
            BigDecimal totalMoney = new BigDecimal("0");
            int quantity = 0;
            for (InboundOrderItem item : inboundOrderItemList) {
                quantity += item.getQuantity();
                totalMoney = totalMoney.add(item.getTotalPrice());
            }
            inboundOrder.setTotalMoney(totalMoney);
            inboundOrder.setTotalQuantity(quantity);
            inboundOrderMapper.update(inboundOrder);
        }
    }

    @Override
    public void auditorWithItems(InboundOrderCreate inboundOrderCreate, String companyId) {
        List<InboundOrderItem> inboundDetails = inboundOrderCreate.getInboundOrderItemList();
        InboundOrder inboundOrder = inboundOrderCreate.getInboundOrder();
        for (InboundOrderItem inboundOrderItem : inboundDetails) {
            //1.1、入库(a、显示根据明细商品属性判断入库方式：批次、序列号、普通；b、再修改总仓库数据)
            if (inboundOrderItem.getType() == InboundType.COMMON)
                inventoryOrdinaryMapper.insert(inboundOrderItem, inboundOrder.getCompanyId());
            else if (inboundOrderItem.getType() == InboundType.BATCH) {
                inventoryBatchMapper.insert(inboundOrderItem, inboundOrder.getCompanyId());
            } else if (inboundOrderItem.getType() == InboundType.SERIAL) {
                //校验同一个商品不能出现重复序列号
                Map<String, Object> params = new HashMap<>();
                params.put("companyId", inboundOrder.getCompanyId());
                params.put("goodsId", inboundOrderItem.getGoodsId());
                List<InventorySerial> inventorySerialList = inventorySerialMapper.selectSerialList(params);
                List<String> list = inventorySerialList.stream().map(InventorySerial::getSerialNo).collect(Collectors.toList());
                List<OrderSerial> serialList = inboundOrderItem.getSerialList();
                List<InventorySerial> addSerialList = new ArrayList<>();
                for (OrderSerial orderSerial : serialList) {
                    if(list.contains(orderSerial.getSerialNo())) {
                        throw new RuntimeException("序列号" + orderSerial.getSerialNo() + "在商品" + inboundOrderItem.getGoodsName() + "中已存在");
                    }
                    InventorySerial serial = new InventorySerial(UUID.randomUUID().toString(), inboundOrder.getCompanyId(), inboundOrderItem.getWarehouseId(), inboundOrderItem.getWarehouseName(),
                            inboundOrderItem.getWarehouseLocationId(), inboundOrderItem.getWarehouseLocationName(), inboundOrderItem.getGoodsId(), orderSerial.getSerialNo(), 0, inboundOrderItem.getUnitName());
                    addSerialList.add(serial);
                }
                inventorySerialMapper.insert(addSerialList, companyId);
            }
            //1.2、根据商品属性判断是否要计算成本
            //入库库存都需要计算成本（分仓核验） - 如下是插入或者修改
            if(inboundOrderItem.getSpecification() == null) inboundOrderItem.setSpecification(""); //防止索引失效，specifaction不能为null
            inventoryMapper.insertWithPrice(inboundOrderItem, inboundOrder.getCompanyId());
        }
        //2 修改入库单状态为已审核
        inboundOrderMapper.updateStatus(inboundOrder.getId(), TableStatus.AUDITED);
        //3. 修改上游单据状态
//        if(inboundOrder.getType() == )
    }

}
